package cn.apienvrypt.advice;

import java.lang.reflect.Type;
import java.util.Objects;
import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import cn.apienvrypt.annotation.Decrypt;
import cn.apienvrypt.config.SecretKeyConfig;
import cn.apienvrypt.context.HandleContext;

/**
 * @author lfj
 */
@ControllerAdvice
public class EncryptRequestBodyAdvice implements RequestBodyAdvice {

	private final Logger log = LoggerFactory.getLogger(this.getClass());

	private boolean encrypt;

	@Resource
	private SecretKeyConfig secretKeyConfig;

	@Override
	public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
		if(Objects.requireNonNull(methodParameter.getMethod())
			.isAnnotationPresent(Decrypt.class) && secretKeyConfig.isOpen()) {
			encrypt = true;
		}
		return encrypt;
	}

	@Override
	public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
		return body;
	}

	@Override
	public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
		Class<? extends HttpMessageConverter<?>> converterType) {
		if(encrypt) {
			try {
				return new DecryptHttpInputMessage(inputMessage, secretKeyConfig.getPrivateKey(), secretKeyConfig.getCharset(), secretKeyConfig.isShowLog());
			} catch(Exception e) {
				HandleContext.remove();
				log.error("解密失败:", e);
			}
		}
		return inputMessage;
	}

	@Override
	public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
		Class<? extends HttpMessageConverter<?>> converterType) {
		return body;
	}
}
